import sys
import tkinter as tk
import traceback
from tkinter import ttk, messagebox, filedialog
import sqlite3
from werkzeug.security import generate_password_hash, check_password_hash
from LibrarySystem.database_option import Database
from LibrarySystem.user_init import User
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class LibraryUI(tk.Toplevel):
    def __init__(self, username, main_window=None, db=None):  # 增加main_window参数
        super().__init__(main_window)
        self.search_term = None
        self._is_destroyed = False
        self.main_window = main_window
        self.protocol("WM_DELETE_WINDOW", self.on_close)
        self.title("图书管理系统")
        self.geometry("1000x900")
        self.configure(bg="#f0f0f0")
        if db:
            try:
                db.conn.execute("SELECT 1")
                self.db = db
            except sqlite3.ProgrammingError:
                self.db = Database()
        else:
            self.db = Database()
        self.style = ttk.Style(self)
        self._setup_style()
        self.selected_books = set()  # 用于存储临时选中的书籍ID
        self.current_category = None  # 当前查看的分类

        # Get user data from database
        user_data = self.db.get_user(username)
        if not user_data:
            messagebox.showerror("Error", "User not found")
            self.destroy()
            return
        self.current_user = User(user_data)
        self.main_frame = None
        self.previous_frame = None
        self.navbar = None
        self.setup_main_ui()
    def _setup_style(self):
        self.style.theme_use('clam')
        self.style.configure('TButton', font=('Arial', 12), padding=6)
        self.style.configure('Header.TLabel', font=('Arial', 16, 'bold'), foreground='#2c3e50')
        self.style.configure('Secondary.TButton', foreground='#34495e', background='#bdc3c7')
        self.style.configure('Treeview', font=('Arial', 11))
        self.style.configure('Treeview.Heading', font=('Arial', 12, 'bold'))
        self.style.map('TButton',
                       background=[('active', '#3498db'), ('!disabled', '#2980b9')],
                       foreground=[('!disabled', 'white')])
        self.style.configure('Sidebar.TFrame', background='#2c3e50')
        self.style.configure('SidebarHeader.TLabel',
                             font=('Arial', 14, 'bold'),
                             foreground='white',
                             background='#34495e')
        self.style.configure('Sidebar.TButton',
                             width=20,
                             anchor='w',
                             foreground='white',
                             background='#34495e',
                             relief='flat')
        self.style.map('Sidebar.TButton',
                       background=[('active', '#3498db')],
                       foreground=[('active', 'white')])
    def clear_frame(self):
        if self.main_frame:
            # 保存当前 frame 的配置信息，而不是 frame 本身
            self.previous_frame = {
                "frame_config": self.main_frame.pack_info(),  # 保存 pack 配置
                "widget_type": "Frame",  # 可以扩展支持其他 widget
                "previous": self.previous_frame  # 维护历史记录
            }
            self.main_frame.destroy()  # 销毁当前 frame
        self.main_frame = ttk.Frame(self)  # 创建新的 frame

    def on_close(self):
        if not self._is_destroyed:
            if messagebox.askokcancel("退出", "确定要退出系统吗？"):
                self._is_destroyed = True
                if self.main_window:
                    self.main_window.destroy()

                sys.exit(0)

    def setup_main_ui(self):
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        self.create_navbar()
        self.show_dashboard()
    def create_navbar(self):
        # Destroy old navbar if exists
        if self.navbar:
            self.navbar.destroy()

        self.navbar = ttk.Frame(self, relief=tk.RAISED)
        self.navbar.pack(side=tk.TOP, fill=tk.X)

        nav_items = [
            ("🏠 首页", self.show_dashboard),
            ("👤 个人信息", self.show_profile),
        ]

        for text, cmd in nav_items:
            btn = ttk.Button(self.navbar, text=text, command=cmd, style='Secondary.TButton')
            btn.pack(side=tk.LEFT, padx=5)
        if self.current_user.role in ['regular']:
            ttk.Button(self.navbar, text="📖 我的借阅", command=self.show_my_borrow_records).pack(side=tk.LEFT, padx=5)
            ttk.Button(self.navbar, text="📚 查找图书", command=self.show_search).pack(side=tk.LEFT, padx=5)
            ttk.Button(self.navbar, text="📚 借阅分类", command=self.show_categories).pack(side=tk.LEFT, padx=5)

        if self.current_user.role in ['librarian']:
            ttk.Button(self.navbar, text="➕ 添加书籍", command=self.show_add_book).pack(side=tk.LEFT, padx=5)
            ttk.Button(self.navbar, text="✏️ 编辑书籍", command=self.show_search).pack(side=tk.LEFT, padx=5)
            ttk.Button(self.navbar, text="📚 所有借阅", command=self.show_all_borrow_records).pack(side=tk.LEFT, padx=5)

        if self.current_user.role == 'sysadmin':
            ttk.Button(self.navbar, text="👥 用户管理", command=self.show_manage_users).pack(side=tk.LEFT, padx=5)
            ttk.Button(self.navbar, text="👥 创建用户", command=self.show_add_user_by_admin).pack(side=tk.LEFT, padx=5)
            ttk.Button(self.navbar, text="📊 系统日志", command=self.show_logs).pack(side=tk.LEFT, padx=5)
            ttk.Button(self.navbar, text="💾 数据备份", command=self.show_backup_ui).pack(side=tk.LEFT, padx=5)

    def show_dashboard(self):
        try:
            # Windows 系统推荐
            plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 微软雅黑
        except:
            try:
                # macOS/Linux 系统备选
                plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei']  # 文泉驿正黑
            except:
                pass
        plt.rcParams['axes.unicode_minus'] = False
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        ttk.Label(self.main_frame, text=f"📖 Welcome to 图书系统", style='Header.TLabel').pack(pady=20)
        ttk.Label(self.main_frame, text=f" 亲爱的 {self.current_user.username}，欢迎使用图书管理系统！",
                  style='Header.TLabel').pack(pady=20)

        # 基础统计卡片
        stats_frame = ttk.Frame(self.main_frame)
        stats_frame.pack(fill=tk.X, pady=10)

        try:
            book_count = self.db.conn.execute("SELECT COUNT(*) FROM books").fetchone()[0]
            user_count = self.db.conn.execute("SELECT COUNT(*) FROM users").fetchone()[0]
            borrowed_count = self.db.conn.execute("SELECT COUNT(*) FROM books WHERE status = 'borrowed'").fetchone()[0]
            total_borrow = self.db.get_total_borrow_count()
        except sqlite3.Error as e:
            print(f"Failed to get stats: {e}")
            book_count = user_count = borrowed_count = total_borrow = 0

        stats = [
            ("总图书量", book_count, "#3498db"),
            ("总用户量", user_count, "#2ecc71"),
            ("在借图书量", borrowed_count, "#e67e22"),
            ("总借阅次数", total_borrow, "#9b59b6")
        ]

        for text, value, color in stats:
            card = ttk.Frame(stats_frame, relief=tk.RIDGE)
            ttk.Label(card, text=text, foreground=color).pack(padx=20, pady=5)
            ttk.Label(card, text=str(value), font=('Arial', 18, 'bold')).pack(padx=20, pady=5)
            card.pack(side=tk.LEFT, expand=True, fill=tk.BOTH, padx=5)

        # 分类借阅统计
        chart_frame = ttk.LabelFrame(self.main_frame,
                                     text="📊 分类借阅统计",
                                     style='Header.TLabel')
        chart_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 获取统计数据
        category_stats = self.db.get_category_borrow_stats()

        if category_stats:
            # 创建Matplotlib图形
            fig = plt.figure(figsize=(6, 4), dpi=80)
            ax = fig.add_subplot(111)

            # 解包数据
            categories = [item[0] for item in category_stats]
            counts = [item[1] for item in category_stats]

            # 设置美观的颜色方案（使用HSL色环生成）
            colors = [
                '#3498db', '#2ecc71', '#e67e22', '#9b59b6',
                '#f1c40f', '#e74c3c', '#1abc9c', '#34495e'
            ]

            # 绘制饼图
            wedges, texts, autotexts = ax.pie(
                counts,
                labels=categories,
                autopct='%1.1f%%',
                startangle=140,
                colors=colors[:len(categories)],
                wedgeprops={'linewidth': 1, 'edgecolor': 'white'},
                textprops={'fontsize': 9}
            )

            # 设置标题和样式
            ax.set_title('分类借阅比例', pad=20, fontsize=12)
            plt.setp(autotexts, size=9, weight="bold", color="white")
            plt.tight_layout()

            # 将图表嵌入Tkinter
            canvas = FigureCanvasTkAgg(fig, master=chart_frame)
            canvas.draw()
            canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        else:
            ttk.Label(chart_frame,
                      text="暂无借阅统计信息",
                      foreground="#95a5a6").pack(pady=50)

        # 热门书籍推荐
        popular_frame = ttk.LabelFrame(self.main_frame, text="🔥 热门图书推荐", style='Header.TLabel')
        popular_frame.pack(fill=tk.BOTH, padx=10, pady=10, expand=True)

        popular_books = self.db.get_popular_books(5)
        for idx, (book_id, title, count) in enumerate(popular_books, 1):
            book_card = ttk.Frame(popular_frame, relief=tk.RIDGE)
            ttk.Label(book_card, text=f"TOP{idx}", foreground="#e74c3c").pack(side=tk.LEFT, padx=10)
            ttk.Label(book_card, text=f"{title}").pack(side=tk.LEFT, padx=10)
            ttk.Label(book_card, text=f"借阅次数：{count}").pack(side=tk.RIGHT, padx=10)
            book_card.pack(fill=tk.X, padx=5, pady=2)
        ttk.Frame(popular_frame).pack(fill=tk.BOTH, expand=True)
        # 在pie图表添加hover效果
        def hover(event):
            if event.inaxes == ax:
                for wedge in wedges:
                    if wedge.contains_point([event.x, event.y]):
                        wedge.set_alpha(0.8)
                    else:
                        wedge.set_alpha(1)
                canvas.draw_idle()

                fig.canvas.mpl_connect("motion_notify_event", hover)


    def show_search(self):
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        # 搜索框部分
        search_frame = ttk.Frame(self.main_frame)
        search_frame.pack(fill=tk.X, pady=10)

        self.search_var = tk.StringVar()
        self.search_var.trace_add("write", lambda *_: self.do_search())
        search_entry = ttk.Entry(search_frame, textvariable=self.search_var, font=('Arial', 12))
        search_entry.pack(side=tk.LEFT, expand=True, fill=tk.X, padx=5)

        # 添加搜索按钮和重置按钮
        btn_frame = ttk.Frame(search_frame)
        btn_frame.pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="搜索", command=self.do_search).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="重置", command=self.reset_search).pack(side=tk.LEFT, padx=2)


        # 书籍表格
        columns = ("ID", "书名", "ISBN", "作者", "所属分类", "状态", "借阅者")
        self.tree = ttk.Treeview(self.main_frame, columns=columns, show='headings', height=15)

        # 配置列
        col_widths = {
            "ID": 60,
            "书名": 200,
            "ISBN": 150,
            "作者": 100,
            "所属分类": 120,
            "状态": 80,
            "借阅者": 100,
        }


        # 添加滚动条
        scrollbar = ttk.Scrollbar(self.main_frame, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 初始加载所有书籍
        self.load_all_books()

        # 绑定事件
        if self.current_user.role in ['librarian']:
            self.tree.bind("<Double-1>", self.edit_selected_book)
        else:
            self.tree.bind("<Double-1>", self.on_book_double_click)

    def load_all_books(self):
        """加载所有书籍"""
        self.search_var.set("")  # 清空搜索条件
        self.do_search()

    def reset_search(self):
        """重置搜索条件"""
        self.search_var.set("")
        self.do_search()


    def do_search(self):
        """执行搜索"""
        for row in self.tree.get_children():
            self.tree.delete(row)

        # 获取搜索条件（空字符串时获取所有书籍）
        search_term = self.search_var.get().strip()
        results = self.db.get_books(search_term) if search_term else self.db.get_all_books()


        if not results:
            messagebox.showinfo("提示", "没有找到匹配的书籍")
        else:
            for book in results:
                book_id = book[0]
                selected = "✓" if book_id in self.selected_books else "□"
                self.tree.insert('', tk.END, values=book + (selected,))

        # 更新全选状态
        self.update_select_all_state(self.tree)

    def show_reserve_book(self, book_id):
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        book = self.db.get_book(book_id)
        if not book:
            messagebox.showerror("错误", "书籍未找到")
            return

        ttk.Label(self.main_frame, text=f"预约书籍: {book[1]}", style='Header.TLabel').pack(pady=20)

        form_frame = ttk.Frame(self.main_frame)
        form_frame.pack(pady=10)

        # 预约日期
        ttk.Label(form_frame, text="预约日期:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.E)
        reserve_date_entry = ttk.Entry(form_frame)
        reserve_date_entry.insert(0, datetime.now().strftime("%Y-%m-%d"))
        reserve_date_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)

        # 预约按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)

        def do_reserve():
            reserve_date = reserve_date_entry.get()
            try:
                datetime.strptime(reserve_date, "%Y-%m-%d")
                success, message = self.db.reserve_book(self.current_user.id, book_id, reserve_date)
                if success:
                    messagebox.showinfo("成功", message)
                    self.show_book_detail(book_id)
                else:
                    messagebox.showerror("错误", message)
            except ValueError:
                messagebox.showerror("错误", "日期格式应为YYYY-MM-DD")

        ttk.Button(btn_frame, text="确认预约", command=do_reserve).pack(side=tk.LEFT, padx=10)
        ttk.Button(btn_frame, text="取消", command=lambda: self.show_book_detail(book_id)).pack(side=tk.LEFT, padx=10)


    def show_categories(self):
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=0, pady=0)

        # 创建主容器
        container = ttk.PanedWindow(self.main_frame, orient=tk.HORIZONTAL)
        container.pack(fill=tk.BOTH, expand=True)

        # 侧边栏框架（固定宽度200）
        sidebar_frame = ttk.Frame(container, width=200, style='Sidebar.TFrame')
        container.add(sidebar_frame)

        # 内容框架（设置权重保证自动拉伸）
        self.category_content_frame = ttk.Frame(container)
        container.add(self.category_content_frame, weight=1)  # 使用 weight 参数

        # 添加分类标题
        ttk.Label(sidebar_frame, text="图书分类", style='SidebarHeader.TLabel').pack(pady=20, padx=10)

        # 添加分类按钮
        categories = self.db.get_categories()
        for category in categories:
            btn = ttk.Button(
                sidebar_frame,
                text=category,
                command=lambda c=category: self.show_books_by_category(c),
                style='Sidebar.TButton'
            )
            btn.pack(fill=tk.X, padx=10, pady=5)

        # 初始显示提示信息
        ttk.Label(
            self.category_content_frame,
            text="请从左侧选择分类查看图书",
            style='Header.TLabel'
        ).pack(expand=True, pady=200)

    def show_books_by_category(self, category):
        # 清空原有内容
        for widget in self.category_content_frame.winfo_children():
            widget.destroy()

        # 添加返回按钮
        header_frame = ttk.Frame(self.category_content_frame)
        header_frame.pack(fill=tk.X, pady=5)

        # 添加分类标题
        ttk.Label(header_frame, text=f"当前分类：{category}", style='Header.TLabel').pack(side=tk.LEFT, padx=10)

        # 添加导出按钮
        ttk.Button(
            header_frame,
            text="导出书籍",
            command=self.show_export_dialog,
            style='TButton'
        ).pack(side=tk.RIGHT, padx=10)

        # 书籍表格
        columns = ("ID", "书名", "ISBN", "作者", "状态", "借阅者", "选择")
        tree = ttk.Treeview(self.category_content_frame, columns=columns, show='headings', height=20)

        # 配置列
        col_widths = {
            "ID": 60,
            "书名": 200,
            "ISBN": 150,
            "作者": 100,
            "状态": 80,
            "借阅者": 100,
            "选择": 50
        }
        for col in columns:
            tree.heading(col, text=col)
            tree.column(col, width=col_widths.get(col, 100), anchor='center' if col == "选择" else 'w')

        # 填充数据
        books = self.db.get_books(category=category)
        for book in books:
            values = (book[0], book[1], book[2], book[3], book[5], book[6])
            tree.insert('', tk.END, values=values + ("□",))

        # 添加滚动条
        scrollbar = ttk.Scrollbar(self.category_content_frame, orient=tk.VERTICAL, command=tree.yview)
        tree.configure(yscrollcommand=scrollbar.set)
        tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 全选复选框
        footer_frame = ttk.Frame(self.category_content_frame)
        footer_frame.pack(fill=tk.X, pady=5)

        self.select_all_var = tk.BooleanVar()
        ttk.Checkbutton(
            footer_frame,
            text="全选",
            variable=self.select_all_var,
            command=lambda: self.toggle_select_all(tree, books)
        ).pack(side=tk.LEFT, padx=10)

        # 绑定事件
        tree.bind("<Button-1>", lambda e: self.on_tree_click(e, tree))
        tree.bind("<Double-1>", self.on_book_double_click)

        self.current_category = category

    def show_profile(self):
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        profile_frame = ttk.Frame(self.main_frame)
        profile_frame.pack(pady=20)

        info = [
            ("👤 用户名", self.current_user.username),
            ("🎭 角色", self.current_user.role),
            ("📧 邮箱", self.current_user.email or "Not set"),
            ("📱 电话", self.current_user.phone or "Not set"),
            ("📅 注册日期", self.current_user.created_at or "Unknown")
        ]

        for i, (label, value) in enumerate(info):
            ttk.Label(profile_frame, text=label, font=('Arial', 12)).grid(row=i, column=0, sticky=tk.W, pady=5)
            ttk.Label(profile_frame, text=value, font=('Arial', 12)).grid(row=i, column=1, sticky=tk.W, pady=5)
        # Add edit info and logout buttons
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)

        ttk.Button(
            btn_frame,
            text="修改个人信息",
            command=self.show_edit_profile,
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)
        ttk.Button(
            btn_frame,
            text="切换账号",
            command=self.switch_account,
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)
        ttk.Button(
            btn_frame,
            text="注销账号",
            command=self.delete_account,  # 修改此处
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)

    def delete_account(self):

            if self.safe_messagebox("确认注销", "确定要永久注销该账号吗？此操作不可逆！"):
                if self.db.delete_user_u(self.current_user.id):
                    messagebox.showinfo("成功", "账号已注销")
                    self.safe_destroy(self)
                if self.main_window and self.main_window.winfo_exists():
                    self.main_window.deiconify()
            else:
                messagebox.showerror("错误", "注销账号失败")
    def safe_destroy(self, window):
        if window and window.winfo_exists():
            try:
                window.destroy()
            except tk.TclError:
                pass

    def safe_messagebox(self, title, message):
        try:
            return messagebox.askyesno(title, message)
        except tk.TclError:
            return False

    class MainApplication:
        _instance = None

        def __new__(cls):
            if not cls._instance:
                cls._instance = super().__new__(cls)
                cls._instance.root = tk.Tk()
                cls._instance.root.withdraw()
            return cls._instance

    def switch_account(self):
        try:
            if self.safe_messagebox("切换账号", "确定要切换账号吗？"):
                self.safe_destroy(self)
                if self.main_window and self.main_window.winfo_exists():
                    self.main_window.deiconify()
        except Exception as e:
            print(f"切换账号失败: {str(e)}")
            traceback.print_exc()

    def show_edit_profile(self):
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # Add back button
        back_frame = ttk.Frame(self.main_frame)
        back_frame.pack(fill=tk.X, pady=5)
        ttk.Button(back_frame, text="← Back", command=self.show_profile).pack(anchor="w", padx=5)

        ttk.Label(self.main_frame, text="✏️ Edit Profile", style='Header.TLabel').pack(pady=20)

        form_frame = ttk.Frame(self.main_frame)
        form_frame.pack(pady=10)

        fields = [
            ("Username", "username", self.current_user.username, False),
            ("Email", "email", self.current_user.email or "", True),
            ("Phone", "phone", self.current_user.phone or "", True),
            ("Old Password", "old_password", "", False),  # New field for old password
            ("New Password", "new_password", "", False),
            ("Confirm Password", "confirm_password", "", False)
        ]

        self.profile_data = {}
        for i, (label, field, value, editable) in enumerate(fields):
            ttk.Label(form_frame, text=label).grid(row=i, column=0, padx=5, pady=5, sticky=tk.E)
            if editable or field.endswith("password"):
                entry = ttk.Entry(form_frame)
                entry.insert(0, value)
                if "password" in field:
                    entry.config(show="*")
                entry.grid(row=i, column=1, padx=5, pady=5)
                self.profile_data[field] = entry
            else:
                ttk.Label(form_frame, text=value).grid(row=i, column=1, padx=5, pady=5, sticky=tk.W)

        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)

        ttk.Button(
            btn_frame,
            text="保存",
            command=self.do_update_profile,
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)

        ttk.Button(
            btn_frame,
            text="取消",
            command=self.show_profile,
            style='Secondary.TButton'
        ).pack(side=tk.LEFT, padx=10)

    def do_update_profile(self):
        data = {k: v.get() for k, v in self.profile_data.items()}

        update_data = {}
        # 只处理密码修改的情况
        if data.get('new_password'):
            # 检查旧密码是否正确
            if not data.get('old_password'):
                messagebox.showwarning("警告", "修改密码需要提供旧密码")
                return
            if not check_password_hash(self.current_user.password_hash, data['old_password']):
                messagebox.showwarning("警告", "旧密码不正确")
                return
            if data['new_password'] != data.get('confirm_password'):
                messagebox.showwarning("警告", "新密码和确认密码不一致")
                return
            update_data['password_hash'] = generate_password_hash(data['new_password'])

        # 处理邮箱和电话
        if data.get('email'):
            if '@' not in data['email'] or '.' not in data['email'].split('@')[1]:
                messagebox.showwarning("警告", "请输入有效的邮箱地址")
                return
            update_data['email'] = data['email']

        if data.get('phone'):
            if not data['phone'].isdigit() or len(data['phone']) != 11:
                messagebox.showwarning("警告", "手机号必须为11位数字")
                return
            update_data['phone'] = data['phone']

        if update_data:
            if self.db.update_user(self.current_user.username, **update_data):
                messagebox.showinfo("成功", "个人信息更新成功")
                # 重新获取用户数据更新缓存
                user_data = self.db.get_user(self.current_user.username)
                if user_data:
                    self.current_user = User(user_data)
                self.show_profile()
            else:
                messagebox.showerror("错误", "更新失败")
        else:
            messagebox.showwarning("提示", "没有需要更新的信息")
    def show_user_context_menu(self, event):
        """Show user right-click menu"""
        item = self.users_tree.identify_row(event.y)
        if not item:
            return

        self.users_tree.selection_set(item)
        user_data = self.users_tree.item(item)['values']

        if not user_data:
            return

        # Can't edit own role or delete self
        can_edit = user_data[0] != self.current_user.id
        can_delete = user_data[0] != self.current_user.id

        menu = tk.Menu(self, tearoff=0)

        menu.add_command(
            label="查看详细信息",
            command=lambda: self.show_user_detail(user_data)
        )

        if can_edit:
            menu.add_command(
                label="修改权限",
                command=lambda: self.show_edit_role(user_data)
            )

        if can_edit:
            menu.add_command(
                label="修改详细信息",
                command=lambda: self.show_edit_user(user_data[1])
            )

        if can_delete:
            menu.add_command(
                label="删除用户",
                command=lambda: self.delete_user(user_data[0])
            )
        print(user_data[0])

        try:
            menu.tk_popup(event.x_root, event.y_root)
        finally:
            menu.grab_release()

    def show_user_detail(self, user_data):
        """Show user details"""
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # Add back button
        back_frame = ttk.Frame(self.main_frame)
        back_frame.pack(fill=tk.X, pady=5)
        ttk.Button(back_frame, text="← Back", command=self.show_manage_users).pack(anchor="w", padx=5)

        ttk.Label(self.main_frame, text=f"👤 User Details - {user_data[1]}", style='Header.TLabel').pack(pady=20)

        detail_frame = ttk.Frame(self.main_frame)
        detail_frame.pack(pady=10)

        labels = [
            ("ID", user_data[0]),
            ("用户名", user_data[1]),
            ("角色", user_data[2]),
            ("邮箱", user_data[3] or "Not set"),
            ("电话", user_data[4] or "Not set"),
            ("注册日期", user_data[5])
        ]

        for i, (text, value) in enumerate(labels):
            ttk.Label(detail_frame, text=text, font=('Arial', 12, 'bold')).grid(row=i, column=0, sticky=tk.E,
                                                                                padx=5, pady=5)
            ttk.Label(detail_frame, text=value, font=('Arial', 12)).grid(row=i, column=1, sticky=tk.W, padx=5,
                                                                         pady=5)

        # Show borrow records
        ttk.Label(detail_frame, text="Borrow Records", font=('Arial', 12, 'bold')).grid(row=len(labels), column=0,
                                                                                        sticky=tk.E, padx=5, pady=5)

        try:
            records = self.db.conn.execute('''SELECT b.title, br.borrow_date, br.return_date 
                                         FROM borrow_records br
                                         JOIN books b ON br.book_id = b.id
                                         WHERE br.user_id = ?''', (user_data[0],)).fetchall()

            if records:
                for i, (title, borrow_date, return_date) in enumerate(records):
                    status = "Returned" if return_date else "Borrowed"
                    ttk.Label(detail_frame, text=f"{title} - {borrow_date} ({status})").grid(
                        row=len(labels) + 1 + i, column=1, sticky=tk.W, padx=5, pady=2)
            else:
                ttk.Label(detail_frame, text="No borrow records").grid(row=len(labels) + 1, column=1, sticky=tk.W,
                                                                       pady=2)
        except sqlite3.Error as e:
            print(f"Failed to get borrow records: {e}")
            ttk.Label(detail_frame, text="Failed to get borrow records").grid(row=len(labels) + 1, column=1,
                                                                              sticky=tk.W,
                                                                              padx=5, pady=2)

    def show_edit_role(self, user_data):
        """Change user role"""
        dialog = tk.Toplevel(self)
        dialog.title("Change User Role")
        dialog.geometry("800x600")
        dialog.resizable(False, False)

        # Add back button
        back_frame = ttk.Frame(dialog)
        back_frame.pack(fill=tk.X, pady=5)
        ttk.Button(back_frame, text="← Back", command=dialog.destroy).pack(anchor="w", padx=5)

        ttk.Label(dialog, text=f"Change {user_data[1]}'s role", style='Header.TLabel').pack(pady=20)

        role_frame = ttk.Frame(dialog)
        role_frame.pack(pady=10)

        roles = ["sysadmin", "librarian", "regular"]
        self.role_var = tk.StringVar(dialog)
        self.role_var.set(user_data[2])

        for i, role in enumerate(roles):
            ttk.Radiobutton(role_frame, text=role, variable=self.role_var, value=role).grid(row=i, column=0, padx=5,
                                                                                           pady=5)

        btn_frame = ttk.Frame(dialog)
        btn_frame.pack(pady=20)

        ttk.Button(
            btn_frame,
            text="保存",
            command=lambda: [self.change_role(user_data[1], self.role_var.get()), dialog.destroy()],
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)
        ttk.Button(
            btn_frame,
            text="取消",
            command=dialog.destroy,
            style='Secondary.TButton'
        ).pack(side=tk.LEFT, padx=10)

    def change_role(self, username, new_role):
        """Save new role"""
        if self.db.update_user(username, role=new_role):
            print(new_role)
            messagebox.showinfo("Success", f"{username}'s role changed to {new_role}")
            self.show_manage_users()
        else:
            messagebox.showerror("Error", "Failed to change role")
            self.show_manage_users()

    def delete_user(self, user_id):
        confirm_msg = f"Delete user {user_id}? 该操作不可撤销，请确认是否继续操作."
        if messagebox.askyesno("Warning", confirm_msg, icon="warning"):
            try:
                if self.db.delete_user(user_id):
                    messagebox.showinfo("Success", "用户已删除")
                    self.show_manage_users()#刷新管理界面
                else:
                    messagebox.showerror("Error", "用户未找到")
                    self.show_manage_users()
            except sqlite3.IntegrityError:
                messagebox.showerror("Error", "该用户有借阅记录，无法删除")
                self.show_manage_users()
            except Exception as e:
                messagebox.showerror("Error", f"操作失败: {str(e)}")
                self.show_manage_users()
    def edit_selected_book(self, event):
        selected_item = self.tree.selection()
        if not selected_item:
            messagebox.showwarning("Warning", "请先选择一本书")
            return

        item = self.tree.item(selected_item[0])
        book_id = item['values'][0]
        self.show_edit_book_form(book_id)
    def show_edit_book_form(self, book_id):
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # Add back button
        back_frame = ttk.Frame(self.main_frame)
        back_frame.pack(fill=tk.X, pady=5)

        ttk.Label(self.main_frame, text="✏ 编辑图书", style='Header.TLabel').pack(pady=20)

        # Get book data
        book_data = self.db.get_book(book_id)
        if not book_data:
            messagebox.showerror("Error", "图书未找到")
            return

        # Create form
        form_frame = ttk.Frame(self.main_frame)
        form_frame.pack(pady=10)
        ttk.Label(form_frame, text="书名").grid(row=0, column=0, padx=5, pady=5, sticky=tk.E)
        self.title_entry = ttk.Entry(form_frame)
        self.title_entry.insert(0, book_data[1])
        self.title_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Label(form_frame, text="ISBN").grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
        self.author_entry = ttk.Entry(form_frame)
        self.author_entry.insert(0, book_data[2])
        self.author_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Label(form_frame, text="作者").grid(row=2, column=0, padx=5, pady=5, sticky=tk.E)
        self.isbn_entry = ttk.Entry(form_frame)
        self.isbn_entry.insert(0, book_data[3])
        self.isbn_entry.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Label(form_frame, text="所属分类").grid(row=3, column=0, padx=5, pady=5, sticky=tk.E)
        self.category_var = tk.StringVar(form_frame)
        self.category_var.set(book_data[4])
        self.category_combo = ttk.Combobox(form_frame, textvariable=self.category_var, state="readonly")
        self.category_combo['values'] = self.db.get_categories()
        self.category_combo.grid(row=3, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Label(form_frame, text="借阅状态").grid(row=4, column=0, padx=5, pady=5, sticky=tk.E)
        self.description_entry = tk.Text(form_frame, height=5, width=50)
        self.description_entry.insert(tk.END, book_data[5])
        self.description_entry.grid(row=4, column=1, padx=5, pady=5, sticky=tk.W)
        # Create buttons
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)
        ttk.Button(
            btn_frame,
            text="保存",
            command=lambda: self.edit_book(book_id),
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)
        ttk.Button(
            btn_frame,
            text="删除",
            command=lambda :self.show_delete_book(book_id),
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)
        ttk.Button(
            btn_frame,
            text="取消",
            command=self.show_search,
            style='Secondary.TButton'
        ).pack(side=tk.LEFT, padx=10)

    def edit_book(self, book_id):
        title = self.title_entry.get()
        isbn = self.author_entry.get()
        author = self.isbn_entry.get()
        category = self.category_var.get()
        description = self.description_entry.get("1.0", "end")

        if self.db.update_book(book_id, title=title, isbn=isbn, author=author, category=category,
                               status=description):
            messagebox.showinfo("成功", "图书更新成功")
            self.show_search()  # 刷新图书列表
        else:
            messagebox.showerror("错误", "更新图书失败")
            self.show_search()
    def show_add_book(self):
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # 返回按钮
        back_frame = ttk.Frame(self.main_frame)
        back_frame.pack(fill=tk.X, pady=5)
        ttk.Label(self.main_frame, text="➕ Add New Book", style='Header.TLabel').pack(pady=20)

        form_frame = ttk.Frame(self.main_frame)
        form_frame.pack(pady=10)

        # 动态生成基础字段
        self.book_data = {}
        base_fields = [
            ("书名", "title"),
            ("ISBN", "isbn"),
            ("作者", "author")
        ]

        # 生成文本输入框
        for row, (label, field) in enumerate(base_fields):
            ttk.Label(form_frame, text=label).grid(row=row, column=0, padx=5, pady=5, sticky=tk.E)
            entry = ttk.Entry(form_frame)
            entry.grid(row=row, column=1, padx=5, pady=5, sticky=tk.W)
            self.book_data[field] = entry

        # 单独处理分类下拉框
        ttk.Label(form_frame, text="分类").grid(row=3, column=0, padx=5, pady=5, sticky=tk.E)
        self.category_var = tk.StringVar()
        self.category_combo = ttk.Combobox(
            form_frame,
            textvariable=self.category_var,
            state="readonly",
            values=self.db.get_categories()  # 从数据库获取分类
        )
        self.category_combo.grid(row=3, column=1, padx=5, pady=5, sticky=tk.W)
        self.book_data["category"] = self.category_var  # 统一保存到字典

        # 按钮区域
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)

        ttk.Button(
            btn_frame,
            text="添加",
            command=self.add_book,
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)

        ttk.Button(
            btn_frame,
            text="清空",
            command=self.show_add_book,
            style='Secondary.TButton'
        ).pack(side=tk.LEFT, padx=10)

        # 添加批量操作按钮
        batch_btn_frame = ttk.Frame(self.main_frame)
        batch_btn_frame.pack(pady=10)

        ttk.Button(
            batch_btn_frame,
            text="批量导入Excel",
            command=self.import_books_from_excel,
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)
    def add_book(self):
        # 统一获取数据的方式
        print("add_book2")
        data = {
            'title': self.book_data['title'].get(),
            'isbn': self.book_data['isbn'].get(),
            'author': self.book_data['author'].get(),
            'category': self.book_data['category'].get()
        }

        # 数据验证
        if not all(data.values()):
            messagebox.showwarning("Warning", "所有字段必须填写")
            return

        if not data['isbn'].isdigit() or len(data['isbn']) not in (10, 13):
            messagebox.showwarning("Warning", "ISBN必须为10或13位数字")
            return

        # 提交到数据库
        if self.db.add_book(data):
            messagebox.showinfo("Success", "书籍添加成功")
            self.show_add_book()
        else:
            messagebox.showerror("Error", "添加失败，ISBN可能已存在")
            self.show_add_book()
    def show_delete_book(self, book_id):
        if messagebox.askyesno("Confirm", f"确定要删除图书 {self.db.get_book_title(book_id)}?"):
            if self.db.delete_book(book_id):
                messagebox.showinfo("Success", f"Book {self.db.get_book_title(book_id)} 删除成功")
                self.show_search()  # 刷新图书列表
            else:
                messagebox.showerror("Error", "删除失败")
                self.show_search()
        else:
            return
    def show_edit_user(self, username):
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # Add back button
        back_frame = ttk.Frame(self.main_frame)
        back_frame.pack(fill=tk.X, pady=5)
        ttk.Label(self.main_frame, text="✏ Edit User", style='Header.TLabel').pack(pady=20)

        # Get user data
        user_data = self.db.get_user(username)
        if not user_data:
            messagebox.showerror("Error", "用户未找到")
            self.show_manage_users()
            return
        # Create form
        form_frame = ttk.Frame(self.main_frame)
        form_frame.pack(pady=10)
        ttk.Label(form_frame, text="用户名").grid(row=0, column=0, padx=5, pady=5, sticky=tk.E)
        self.username_entry = ttk.Entry(form_frame)
        self.username_entry.insert(0, user_data[1])
        self.username_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Label(form_frame, text="密码").grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
        self.password_entry = ttk.Entry(form_frame, show="*")
        self.password_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Label(form_frame, text="邮箱").grid(row=2, column=0, padx=5, pady=5, sticky=tk.E)
        self.email_entry = ttk.Entry(form_frame)
        self.email_entry.insert(0, user_data[4])
        self.email_entry.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W)
        ttk.Label(form_frame, text="电话").grid(row=3, column=0, padx=5, pady=5, sticky=tk.E)
        self.phone_entry = ttk.Entry(form_frame)
        self.phone_entry.insert(0, user_data[5])
        self.phone_entry.grid(row=3, column=1, padx=5, pady=5, sticky=tk.W)
        # Create buttons
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)
        ttk.Button(
            btn_frame,
            text="保存",
            command=lambda: self.update_user(username),
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)
        ttk.Button(
            btn_frame,
            text="取消",
            command=self.show_manage_users,
            style='Secondary.TButton'
        ).pack(side=tk.LEFT, padx=10)
    def show_manage_users(self):
        self.clear_frame()
        if self.main_frame.winfo_ismapped():
            self.previous_frame = {
                "frame": self.main_frame,
                "previous": self.previous_frame
            }
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # 标题
        ttk.Label(self.main_frame, text="👥 用户管理", style="Header.TLabel").pack(pady=10)

        # 用户表格
        columns = ("ID", "Username", "Role", "Email", "Phone", "Registration Date")
        self.users_tree = ttk.Treeview(self.main_frame, columns=columns, show="headings", selectmode="browse")
        for col in columns:
            self.users_tree.heading(col, text=col)
            self.users_tree.column(col, width=100 if col == "ID" else 120)
        self.users_tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        self.refresh_users_list()  # 初始化数据

        # 操作按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=10)
        ttk.Button(btn_frame, text="刷新", command=self.refresh_users_list, style="TButton").pack(side=tk.LEFT,
                                                                                                     padx=5)

        # 右键菜单
        self.users_tree.bind("<Button-3>", self.show_user_context_menu)

    def refresh_users_list(self):
        """刷新用户列表数据"""
        for row in self.users_tree.get_children():
            self.users_tree.delete(row)
        try:
            users = self.db.get_all_users()  # 确保方法返回完整数据
            for user in users:
                self.users_tree.insert("", "end", values=user)
        except sqlite3.Error as e:
            messagebox.showerror("Database Error", f"Failed to load users: {str(e)}")
    def update_user(self, username):
        """Update user information based on username"""
        # Get input values from GUI fields
        new_username = self.username_entry.get()
        new_password = self.password_entry.get()
        new_email = self.email_entry.get()
        new_phone = self.phone_entry.get()

        # Validate required fields
        if not new_username:
            messagebox.showwarning("Warning", "用户名不能为空")

            return

        # Prepare update data
        update_data = {
            'username': new_username,
            'password_hash': generate_password_hash(new_password)
        }

        # Add optional fields if provided
        if new_email:
            update_data['email'] = new_email
        if new_phone:
            update_data['phone'] = new_phone

        # Update user in database
        if self.db.update_user(username, **update_data):
            messagebox.showinfo("Success", "修改成功")
            self.show_manage_users()
        else:
            messagebox.showerror("Error", "修改失败")

    def show_add_user_by_admin(self):
        """管理员添加用户界面"""
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        ttk.Label(self.main_frame, text="👥 添加新用户", style='Header.TLabel').pack(pady=20)

        form_frame = ttk.Frame(self.main_frame)
        form_frame.pack(pady=10)

        # 用户名
        ttk.Label(form_frame, text="用户名:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.E)
        username_entry = ttk.Entry(form_frame)
        username_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)

        # 密码
        ttk.Label(form_frame, text="密码:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
        password_entry = ttk.Entry(form_frame, show="*")
        password_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W)

        # 角色
        ttk.Label(form_frame, text="角色:").grid(row=2, column=0, padx=5, pady=5, sticky=tk.E)
        role_var = tk.StringVar(value="regular")
        role_menu = ttk.OptionMenu(form_frame, role_var, "regular", "regular", "librarian")
        role_menu.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W)

        # 邮箱
        ttk.Label(form_frame, text="邮箱:").grid(row=3, column=0, padx=5, pady=5, sticky=tk.E)
        email_entry = ttk.Entry(form_frame)
        email_entry.grid(row=3, column=1, padx=5, pady=5, sticky=tk.W)



        # 按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)

        def add_user():
            username = username_entry.get()
            password = password_entry.get()
            role = role_var.get()
            email = email_entry.get()


            success, message = self.db.add_user_by_admin(username, password, role, email)
            if success:
                messagebox.showinfo("成功", message)
                self.show_manage_users()
            else:
                messagebox.showerror("错误", message)

        ttk.Button(btn_frame, text="添加", command=add_user).pack(side=tk.LEFT, padx=10)
        ttk.Button(btn_frame, text="取消", command=self.show_manage_users).pack(side=tk.LEFT, padx=10)

    def show_book_detail(self, book_id):
        """显示书籍详情和借阅信息"""
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        book = self.db.get_book(book_id)
        if not book:
            messagebox.showerror("错误", "书籍未找到")
            return

        # 书籍基本信息
        ttk.Label(self.main_frame, text=f"📖 {book[1]}", style='Header.TLabel').pack(pady=10)

        info_frame = ttk.Frame(self.main_frame)
        info_frame.pack(fill=tk.X, pady=10)

        details = [
            ("ISBN:", book[2]),
            ("作者:", book[3]),
            ("分类:", book[4]),
            ("状态:", book[5])
        ]

        for i, (label, value) in enumerate(details):
            ttk.Label(info_frame, text=label, font=('Arial', 12, 'bold')).grid(row=i, column=0, sticky=tk.E, padx=5,
                                                                               pady=5)
            ttk.Label(info_frame, text=value, font=('Arial', 12)).grid(row=i, column=1, sticky=tk.W, padx=5, pady=5)

        # 借阅信息 - 获取当前书籍的借阅记录
        borrow_records = self.db.get_all_borrow_records()  # 获取所有借阅记录
        current_borrow_record = None

        # 查找当前书籍的未归还记录
        for record in borrow_records:
            if record[2] == book[1] and record[5] is None:  # 匹配书名且未归还
                current_borrow_record = record
                break

        if current_borrow_record:
            ttk.Label(self.main_frame, text="借阅信息", style='Header.TLabel').pack(pady=10)
            borrow_frame = ttk.Frame(self.main_frame)
            borrow_frame.pack(fill=tk.X, pady=10)

            ttk.Label(borrow_frame, text="借阅人:", font=('Arial', 12, 'bold')).grid(row=0, column=0, sticky=tk.E,
                                                                                     padx=5, pady=5)
            ttk.Label(borrow_frame, text=current_borrow_record[1], font=('Arial', 12)).grid(row=0, column=1,
                                                                                            sticky=tk.W, padx=5,
                                                                                            pady=5)

            ttk.Label(borrow_frame, text="借阅日期:", font=('Arial', 12, 'bold')).grid(row=1, column=0, sticky=tk.E,
                                                                                       padx=5, pady=5)
            ttk.Label(borrow_frame, text=current_borrow_record[3], font=('Arial', 12)).grid(row=1, column=1,
                                                                                            sticky=tk.W, padx=5,
                                                                                            pady=5)

            # 如果是管理员，显示强制归还按钮
            if self.current_user.role in ['librarian', 'sysadmin']:
                btn_frame = ttk.Frame(self.main_frame)
                btn_frame.pack(pady=20)

                def force_return():
                    success, message = self.db.force_return_book(current_borrow_record[0])  # 使用记录ID
                    if success:
                        messagebox.showinfo("成功", message)
                        self.show_book_detail(book_id)  # 刷新页面
                    else:
                        messagebox.showerror("错误", message)

                ttk.Button(btn_frame, text="强制归还", command=force_return).pack(side=tk.LEFT, padx=10)

        # 如果是普通用户且书籍可借，显示借阅表单
        elif self.current_user.role == 'regular' and book[5] == 'available':
            ttk.Label(self.main_frame, text="借阅此书", style='Header.TLabel').pack(pady=10)

            borrow_form = ttk.Frame(self.main_frame)
            borrow_form.pack(fill=tk.X, pady=10)

            # 借阅日期
            ttk.Label(borrow_form, text="借阅日期:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.E)
            borrow_date_entry = ttk.Entry(borrow_form)
            borrow_date_entry.insert(0, datetime.now().strftime("%Y-%m-%d"))
            borrow_date_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)

            # 预计归还日期
            ttk.Label(borrow_form, text="预计归还日期:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
            return_date_entry = ttk.Entry(borrow_form)
            return_date_entry.insert(0, (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d"))
            return_date_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W)

            def borrow_book():
                borrow_date = borrow_date_entry.get()
                return_date = return_date_entry.get()

                try:
                    # 检查日期格式
                    datetime.strptime(borrow_date, "%Y-%m-%d")
                    datetime.strptime(return_date, "%Y-%m-%d")

                    # 如果是当前日期，直接借阅；否则视为预约
                    if borrow_date == datetime.now().strftime("%Y-%m-%d"):
                        if self.db.borrow_book(self.current_user.id, book_id):
                            messagebox.showinfo("成功", "书籍借阅成功")
                            self.show_book_detail(book_id)  # 刷新页面
                        else:
                            messagebox.showerror("错误", "借阅失败")
                    else:

                        self.show_reserve_book(book_id)
                except ValueError:
                    messagebox.showerror("错误", "日期格式应为YYYY-MM-DD")

            btn_frame = ttk.Frame(self.main_frame)
            btn_frame.pack(pady=20)
            ttk.Button(btn_frame, text="借阅", command=borrow_book).pack(side=tk.LEFT, padx=10)

        # 返回按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)
        ttk.Button(btn_frame, text="返回", command=self.show_search).pack(side=tk.LEFT, padx=10)

    def on_book_double_click(self, event):
        """处理书籍双击事件"""
        tree = event.widget  # 获取触发事件的Treeview组件
        selected_item = tree.selection()  # 获取选中的项

        if selected_item:  # 确保有选中项
            item = tree.item(selected_item[0])
            book_id = item['values'][0]  # 假设ID是第一列
            self.show_book_detail(book_id)  # 调用显示书籍详情的方法
    def select_backup_path(self):
        path = filedialog.asksaveasfilename(
            title="选择备份位置",
            defaultextension=".db",
            filetypes=[("SQLite Database", "*.db"), ("All Files", "*.*")]
        )
        if path:
            self.backup_path_entry.delete(0, tk.END)
            self.backup_path_entry.insert(0, path)

    def do_backup(self):
        backup_path = self.backup_path_entry.get()
        if not backup_path:
            messagebox.showwarning("警告", "请选择备份路径")
            return

        success, message = self.db.backup_database(backup_path)
        if success:
            messagebox.showinfo("成功", message)
        else:
            messagebox.showerror("错误", message)



    def show_my_borrow_records(self):
        """显示当前用户的借阅记录"""
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        ttk.Label(self.main_frame, text="📖 我的借阅记录", style='Header.TLabel').pack(pady=10)

        # 借阅记录表格
        columns = ("ID", "书名", "借阅日期", "应还日期", "状态", "续借次数")
        tree = ttk.Treeview(self.main_frame, columns=columns, show="headings")
        for col in columns:
            tree.heading(col, text=col)
        tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 填充数据
        records = self.db.get_user_borrow_records(self.current_user.id)
        for record in records:
            status = "已归还" if record[4] else "借阅中"
            renew_count = record[5] if len(record) > 5 else 0  # 确保有续借次数字段
            tree.insert("", "end", values=(record[0], record[1], record[2], record[3], status, renew_count))

        # 添加操作按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=10)

        def return_book():
            selected = tree.selection()
            if not selected:
                messagebox.showwarning("警告", "请选择要归还的书籍")
                return

            record_id = tree.item(selected[0])['values'][0]
            if self.db.force_return_book(record_id):
                messagebox.showinfo("成功", "书籍归还成功")
                self.show_my_borrow_records()
            else:
                messagebox.showerror("错误", "归还失败")

        def renew_book():
            selected = tree.selection()
            if not selected:
                messagebox.showwarning("警告", "请选择要续借的书籍")
                return

            record = tree.item(selected[0])['values']
            if record[4] == "已归还":
                messagebox.showwarning("警告", "已归还的书籍不能续借")
                return

            book_id = self.db.conn.execute(
                "SELECT book_id FROM borrow_records WHERE id = ?",
                (record[0],)
            ).fetchone()[0]

            success, message = self.db.renew_book(book_id, self.current_user.id)
            if success:
                messagebox.showinfo("成功", message)
                self.show_my_borrow_records()
            else:
                messagebox.showerror("错误", message)

        ttk.Button(btn_frame, text="归还书籍", command=return_book).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="续借", command=renew_book).pack(side=tk.LEFT, padx=5)


        # 显示预约记录
        ttk.Label(self.main_frame, text="📅 我的预约记录", style='Header.TLabel').pack(pady=10)
        res_columns = ("ID", "书名", "预约日期", "过期日期", "状态")
        res_tree = ttk.Treeview(self.main_frame, columns=res_columns, show="headings")
        for col in res_columns:
            res_tree.heading(col, text=col)
        res_tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 填充预约数据
        reservations = self.db.get_user_reservations(self.current_user.id)
        for res in reservations:
            res_tree.insert("", "end", values=res)

        # 预约操作按钮
        res_btn_frame = ttk.Frame(self.main_frame)
        res_btn_frame.pack(pady=10)

        def cancel_reservation():
            selected = res_tree.selection()
            if not selected:
                messagebox.showwarning("警告", "请选择要取消的预约")
                return

            res_id = res_tree.item(selected[0])['values'][0]
            if self.db.delete_reservation(res_id,self.current_user.id):
                messagebox.showinfo("成功", "预约已取消")
                self.show_my_borrow_records()
            else:
                messagebox.showerror("错误", "取消预约失败")

        def modify_reservation():
            selected = res_tree.selection()
            if not selected:
                messagebox.showwarning("警告", "请选择要修改的预约")
                return

            res_id = res_tree.item(selected[0])['values'][0]
            self.show_modify_reservation(res_id)

        ttk.Button(res_btn_frame, text="取消预约", command=cancel_reservation).pack(side=tk.LEFT, padx=5)
        ttk.Button(res_btn_frame, text="修改预约", command=modify_reservation).pack(side=tk.LEFT, padx=5)

    def show_all_borrow_records(self):
        """显示所有借阅记录(管理员用)"""
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        ttk.Label(self.main_frame, text="📖 所有借阅记录", style='Header.TLabel').pack(pady=10)

        # 借阅记录表格
        columns = ("ID", "用户名", "书名", "借阅日期", "应还日期", "归还日期", "续借次数")
        tree = ttk.Treeview(self.main_frame, columns=columns, show="headings")
        for col in columns:
            tree.heading(col, text=col)
        tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 填充数据
        records = self.db.get_all_borrow_records()
        for record in records:
            tree.insert("", "end", values=record)

        # 添加操作按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=10)
        # 逾期记录表格
        ttk.Label(self.main_frame, text="🫵 所有逾期记录", style='Header.TLabel').pack(pady=10)
        columns = ( "用户名", "书名", "逾期日期")
        tree = ttk.Treeview(self.main_frame, columns=columns, show="headings")
        for col in columns:
            tree.heading(col, text=col)
        tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 填充数据
        due_books = self.db.check_overdue_books()
        for due_book in due_books:
            tree.insert("", "end", values=due_book)

        # 添加操作按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=10)
        def force_return():
            selected = tree.selection()
            if not selected:
                messagebox.showwarning("警告", "请选择要归还的书籍")
                return

            record_id = tree.item(selected[0])['values'][0]
            success, message = self.db.force_return_book(record_id)
            if success:
                messagebox.showinfo("成功", message)
                self.show_all_borrow_records()
            else:
                messagebox.showerror("错误", message)

        ttk.Button(btn_frame, text="强制归还", command=force_return).pack(side=tk.LEFT, padx=5)



        # 显示所有预约记录
        ttk.Label(self.main_frame, text="📅 所有预约记录", style='Header.TLabel').pack(pady=10)
        res_columns = ("ID", "用户名", "书名", "预约日期", "过期日期", "状态")
        res_tree = ttk.Treeview(self.main_frame, columns=res_columns, show="headings")
        for col in res_columns:
            res_tree.heading(col, text=col)
        res_tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 填充预约数据
        reservations = self.db.get_all_reservations()
        for res in reservations:
            res_tree.insert("", "end", values=res)
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=10)

        ttk.Button(
            btn_frame,
            text="导出选中记录",
            command=lambda: self.export_selected_borrow_records(tree),
            style='TButton'
        ).pack(side=tk.LEFT, padx=5)

        ttk.Button(
            btn_frame,
            text="导出全部记录",
            command=lambda: self.export_selected_borrow_records(tree, all_records=True),
            style='TButton'
        ).pack(side=tk.LEFT, padx=5)

        # 预约操作按钮(管理员)
        res_btn_frame = ttk.Frame(self.main_frame)
        res_btn_frame.pack(pady=10)

        def admin_cancel_reservation():
            selected = res_tree.selection()
            if not selected:
                messagebox.showwarning("警告", "请选择要取消的预约")
                return

            res_id = res_tree.item(selected[0])['values'][0]
            if self.db.delete_reservation(res_id):
                messagebox.showinfo("成功", "预约已取消")
                self.show_all_borrow_records()
            else:
                messagebox.showerror("错误", "取消预约失败")

        def admin_modify_reservation():
            selected = res_tree.selection()
            if not selected:
                messagebox.showwarning("警告", "请选择要修改的预约")
                return

            res_id = res_tree.item(selected[0])['values'][0]
            self.show_modify_reservation(res_id, admin=True)

        ttk.Button(res_btn_frame, text="取消预约", command=admin_cancel_reservation).pack(side=tk.LEFT, padx=5)
        ttk.Button(res_btn_frame, text="修改预约", command=admin_modify_reservation).pack(side=tk.LEFT, padx=5)

    def show_modify_reservation(self, reservation_id, admin=False):
        """修改预约信息界面"""
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        # 获取预约信息
        reservation = None
        if admin:
            reservations = self.db.get_all_reservations()
        else:
            reservations = self.db.get_user_reservations(self.current_user.id)

        for res in reservations:
            if res[0] == reservation_id:
                reservation = res
                break
        if not reservation:
            messagebox.showerror("错误", "预约记录未找到")
            if admin:
                self.show_all_borrow_records()
            else:
                self.show_my_borrow_records()
            return

        ttk.Label(self.main_frame, text="✏️ 修改预约信息", style='Header.TLabel').pack(pady=10)

        form_frame = ttk.Frame(self.main_frame)
        form_frame.pack(pady=10)
        #预约书籍
        ttk.Label(form_frame, text="预约书籍:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.E)
        book_name_entry = ttk.Entry(form_frame)
        book_name_entry.insert(0, reservation[2])
        book_name_entry.grid(row=0, column=1, padx=5, pady=5)
        # 预约日期
        ttk.Label(form_frame, text="预约日期:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
        reserve_date_entry = ttk.Entry(form_frame)
        reserve_date_entry.insert(0, reservation[3])
        reserve_date_entry.grid(row=1, column=1, padx=5, pady=5)

        # 过期日期
        ttk.Label(form_frame, text="过期日期:").grid(row=2, column=0, padx=5, pady=5, sticky=tk.E)
        expire_date_entry = ttk.Entry(form_frame)
        expire_date_entry.insert(0, reservation[4])
        expire_date_entry.grid(row=2, column=1, padx=5, pady=5)

        # 状态(仅管理员可修改)
        if admin:
            ttk.Label(form_frame, text="状态:").grid(row=3, column=0, padx=5, pady=5, sticky=tk.E)
            status_var = tk.StringVar(value=reservation[4])
            status_menu = ttk.OptionMenu(form_frame, status_var, reservation[5],
                                         "pending", "completed", "canceled", "expired")
            status_menu.grid(row=3, column=1, padx=5, pady=5)

        # 按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=10)

        def save_changes():
            update_data = {
                'reserve_date': reserve_date_entry.get(),
                'expire_date': expire_date_entry.get()
            }
            if admin:
                update_data['status'] = status_var.get()

            if self.db.update_reservation(reservation_id, **update_data):
                messagebox.showinfo("成功", "预约信息已更新")
                if admin:
                    self.show_all_borrow_records()
                else:
                    self.show_my_borrow_records()
            else:
                messagebox.showerror("错误", "更新失败")

        ttk.Button(btn_frame, text="保存", command=save_changes).pack(side=tk.LEFT, padx=5)

        def cancel():
            if admin:
                self.show_all_borrow_records()
            else:
                self.show_my_borrow_records()

        ttk.Button(btn_frame, text="取消", command=cancel).pack(side=tk.LEFT, padx=5)

    def show_logs(self):
        """显示系统日志(仅sysadmin)"""
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        ttk.Label(self.main_frame, text="📊 系统日志", style='Header.TLabel').pack(pady=10)

        # 日志表格
        columns = ("ID", "用户ID", "操作", "详情", "时间")
        tree = ttk.Treeview(self.main_frame, columns=columns, show="headings")
        for col in columns:
            tree.heading(col, text=col)
        tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 填充数据
        try:
            cursor = self.db.conn.execute('''SELECT l.id, u.username, l.action, l.details, l.timestamp 
                                          FROM logs l
                                          LEFT JOIN users u ON l.user_id = u.id
                                          ORDER BY l.timestamp DESC''')
            logs = cursor.fetchall()

            for log in logs:
                tree.insert("", "end", values=log)

        except sqlite3.Error as e:
            messagebox.showerror("错误", f"获取日志失败: {str(e)}")

        # 添加过滤和导出功能
        filter_frame = ttk.Frame(self.main_frame)
        filter_frame.pack(fill=tk.X, pady=10)

        ttk.Label(filter_frame, text="用户:").pack(side=tk.LEFT, padx=5)
        self.log_user_var = tk.StringVar()
        user_combo = ttk.Combobox(filter_frame, textvariable=self.log_user_var)
        user_combo['values'] = [u[1] for u in self.db.get_all_users()]
        user_combo.pack(side=tk.LEFT, padx=5)

        ttk.Label(filter_frame, text="操作类型:").pack(side=tk.LEFT, padx=5)
        self.log_action_var = tk.StringVar()
        action_combo = ttk.Combobox(filter_frame, textvariable=self.log_action_var)
        action_combo['values'] = ['BORROW', 'RETURN', 'RENEW', 'LOGIN', 'ADD', 'EDIT', 'DELETE']
        action_combo.pack(side=tk.LEFT, padx=5)

        ttk.Button(filter_frame, text="筛选", command=self.filter_logs).pack(side=tk.LEFT, padx=5)
        ttk.Button(filter_frame, text="导出日志", command=self.export_logs).pack(side=tk.LEFT, padx=5)
        ttk.Button(filter_frame, text="清除筛选", command=self.show_logs).pack(side=tk.LEFT, padx=5)

    def filter_logs(self):
        """根据条件筛选日志"""
        # 获取筛选条件
        username = self.log_user_var.get()
        action = self.log_action_var.get()

        # 构建SQL查询
        query = '''SELECT l.id, u.username, l.action, l.details, l.timestamp 
                   FROM logs l
                   LEFT JOIN users u ON l.user_id = u.id
                   WHERE 1=1'''
        params = []

        # 添加用户名筛选条件
        if username:
            query += " AND u.username = ?"
            params.append(username)

        # 添加操作类型筛选条件
        if action:
            query += " AND l.action = ?"
            params.append(action)

        # 按时间降序排列
        query += " ORDER BY l.timestamp DESC"

        try:
            # 清空当前表格
            for item in self.main_frame.winfo_children():
                if isinstance(item, ttk.Treeview):
                    for row in item.get_children():
                        item.delete(row)

            # 执行查询并填充数据
            cursor = self.db.conn.execute(query, params)
            logs = cursor.fetchall()

            # 找到Treeview控件
            for widget in self.main_frame.winfo_children():
                if isinstance(widget, ttk.Treeview):
                    tree = widget
                    break
            else:
                raise ValueError("找不到Treeview控件")

            # 插入筛选后的数据
            for log in logs:
                tree.insert("", "end", values=log)

        except sqlite3.Error as e:
            messagebox.showerror("错误", f"筛选日志失败: {str(e)}")
        except ValueError as e:
            messagebox.showerror("错误", str(e))
        except Exception as e:
            messagebox.showerror("错误", f"发生未预期错误: {str(e)}")

    def export_logs(self):
        """导出日志到文件"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".csv",
            filetypes=[("CSV Files", "*.csv"), ("All Files", "*.*")]
        )
        if not file_path:
            return

        try:
            cursor = self.db.conn.execute('''SELECT u.username, l.action, l.details, l.timestamp 
                                          FROM logs l
                                          LEFT JOIN users u ON l.user_id = u.id
                                          ORDER BY l.timestamp DESC''')
            logs = cursor.fetchall()

            with open(file_path, 'w', encoding='utf-8') as f:
                f.write("用户名,操作类型,详情,时间\n")
                for log in logs:
                    f.write(f'"{log[0]}","{log[1]}","{log[2]}","{log[3]}"\n')

            messagebox.showinfo("成功", f"日志已导出到 {file_path}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")

    def show_backup_ui(self):
        """显示数据备份界面"""
        self.clear_frame()
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        ttk.Label(self.main_frame, text="💾 数据备份与恢复", style='Header.TLabel').pack(pady=20)

        backup_frame = ttk.Frame(self.main_frame)
        backup_frame.pack(pady=10)

        # 备份路径
        ttk.Label(backup_frame, text="备份路径:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.E)
        self.backup_path_entry = ttk.Entry(backup_frame, width=40)
        self.backup_path_entry.grid(row=0, column=1, padx=5, pady=5)
        ttk.Button(backup_frame, text="浏览...", command=self.select_backup_path).grid(row=0, column=2, padx=5)

        # 恢复路径
        ttk.Label(backup_frame, text="恢复路径:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.E)
        self.restore_path_entry = ttk.Entry(backup_frame, width=40)
        self.restore_path_entry.grid(row=1, column=1, padx=5, pady=5)
        ttk.Button(backup_frame, text="浏览...", command=self.select_restore_path).grid(row=1, column=2, padx=5)

        # 按钮
        btn_frame = ttk.Frame(self.main_frame)
        btn_frame.pack(pady=20)

        ttk.Button(btn_frame, text="执行备份", command=self.do_backup).pack(side=tk.LEFT, padx=10)
        ttk.Button(btn_frame, text="恢复数据", command=self.do_restore).pack(side=tk.LEFT, padx=10)
        ttk.Button(btn_frame, text="返回", command=self.setup_main_ui).pack(side=tk.LEFT, padx=10)

    def select_restore_path(self):
        path = filedialog.askopenfilename(
            title="选择恢复文件",
            filetypes=[("SQLite Database", "*.db"), ("All Files", "*.*")]
        )
        if path:
            self.restore_path_entry.delete(0, tk.END)
            self.restore_path_entry.insert(0, path)
    def do_restore(self):
        restore_path = self.restore_path_entry.get()
        if not restore_path:
            messagebox.showwarning("警告", "请选择恢复文件")
            return

        if not messagebox.askyesno("确认", "恢复数据将覆盖当前数据库，确定继续吗？"):
            return

        try:
            # 关闭当前连接
            self.db.conn.close()

            # 复制备份文件
            import shutil
            shutil.copyfile(restore_path, './library.db')

            # 重新连接数据库
            self.db = Database()
            messagebox.showinfo("成功", "数据恢复成功，请重新登录")
            self.destroy()
        except Exception as e:
            messagebox.showerror("错误", f"恢复失败: {str(e)}")
            self.db = Database()  # 尝试重新连接

    def import_books_from_excel(self):
        """从Excel文件导入书籍"""
        file_path = filedialog.askopenfilename(
            title="选择Excel文件",
            filetypes=[("Excel Files", "*.xlsx *.xls"), ("All Files", "*.*")]
        )

        if not file_path:
            return

        # 显示进度对话框
        progress = tk.Toplevel(self)
        progress.title("导入进度")
        progress.geometry("300x100")
        ttk.Label(progress, text="正在导入书籍，请稍候...").pack(pady=20)
        progress.update()

        try:
            success, message = self.db.import_books_from_excel(file_path)
            progress.destroy()
            if success:
                messagebox.showinfo("成功", message)
            else:
                messagebox.showerror("错误", message)
        except Exception as e:
            progress.destroy()
            messagebox.showerror("错误", f"导入失败: {str(e)}")


    def export_selected_borrow_records(self, tree, all_records=False):
        """导出选中的借阅记录"""
        if all_records:
            selected_ids = None
        else:
            selected_items = tree.selection()
            if not selected_items:
                messagebox.showwarning("警告", "请先选择要导出的记录")
                return
            selected_ids = [tree.item(item)['values'][0] for item in selected_items]

        file_path = filedialog.asksaveasfilename(
            title="保存Excel文件",
            defaultextension=".xlsx",
            filetypes=[("Excel Files", "*.xlsx"), ("All Files", "*.*")]
        )

        if not file_path:
            return

        # 显示进度对话框
        progress = tk.Toplevel(self)
        progress.title("导出进度")
        progress.geometry("300x100")
        ttk.Label(progress, text="正在导出记录，请稍候...").pack(pady=20)
        progress.update()

        try:
            success, message = self.db.export_borrow_records_to_excel(file_path, selected_ids)
            progress.destroy()
            if success:
                messagebox.showinfo("成功", message)
            else:
                messagebox.showerror("错误", message)
        except Exception as e:
            progress.destroy()
            messagebox.showerror("错误", f"导出失败: {str(e)}")

    def on_tree_click(self, event, tree):
        """处理树形视图点击事件，实现复选框功能"""
        region = tree.identify("region", event.x, event.y)
        column = tree.identify_column(event.x)

        if region == "cell" and column == "#7":  # 点击了选择列
            item = tree.identify_row(event.y)
            current_value = tree.set(item, "选择")
            new_value = "✓" if current_value == "□" else "□"
            tree.set(item, "选择", new_value)

            # 更新选中书籍集合
            book_id = tree.item(item)['values'][0]
            if new_value == "✓":
                self.selected_books.add(book_id)
            else:
                self.selected_books.discard(book_id)

            # 更新全选复选框状态
            self.update_select_all_state(tree)

    def toggle_select_all(self, tree, books):
        """全选/取消全选所有书籍"""
        if self.select_all_var.get():
            # 全选
            for item in tree.get_children():
                tree.set(item, "选择", "✓")
                book_id = tree.item(item)['values'][0]
                self.selected_books.add(book_id)
        else:
            # 取消全选
            for item in tree.get_children():
                tree.set(item, "选择", "□")
                book_id = tree.item(item)['values'][0]
                self.selected_books.discard(book_id)

    def update_select_all_state(self, tree=None):
        """更新全选复选框状态"""
        try:
            # 如果没有传入tree，使用默认的self.tree
            if tree is None:
                tree = self.tree

            # 如果仍然没有tree对象则直接返回
            if not tree:
                return

            # 检查是否有"选择"列
            columns = tree['columns']
            if "选择" not in columns:
                return

            all_selected = all(tree.set(item, "选择") == "✓" for item in tree.get_children())
            if hasattr(self, 'select_all_var'):
                self.select_all_var.set(all_selected)
        except Exception as e:
            print(f"更新全选状态时出错: {e}")
            # 可以选择记录日志或静默处理

    def show_export_dialog(self):
        """显示导出对话框"""
        if not self.selected_books:
            messagebox.showwarning("警告", "请先选择要导出的书籍")
            return

        # 创建导出对话框
        export_dialog = tk.Toplevel(self)
        export_dialog.title("导出书籍")
        export_dialog.geometry("400x200")

        # 显示已选书籍数量
        ttk.Label(
            export_dialog,
            text=f"已选择 {len(self.selected_books)} 本书籍",
            font=('Arial', 12)
        ).pack(pady=10)

        # 添加导出选项
        option_frame = ttk.Frame(export_dialog)
        option_frame.pack(pady=10)

        ttk.Label(option_frame, text="导出格式:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        export_format = ttk.Combobox(option_frame, values=["Excel (.xlsx)"], state="readonly")
        export_format.current(0)
        export_format.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)

        # 添加按钮
        btn_frame = ttk.Frame(export_dialog)
        btn_frame.pack(pady=20)

        ttk.Button(
            btn_frame,
            text="导出",
            command=lambda: self.do_export_books(export_dialog),
            style='TButton'
        ).pack(side=tk.LEFT, padx=10)

        ttk.Button(
            btn_frame,
            text="取消",
            command=export_dialog.destroy,
            style='Secondary.TButton'
        ).pack(side=tk.LEFT, padx=10)

    def do_export_books(self, dialog):
        """执行导出操作"""
        file_path = filedialog.asksaveasfilename(
            title="保存Excel文件",
            defaultextension=".xlsx",
            filetypes=[("Excel Files", "*.xlsx"), ("All Files", "*.*")]
        )

        if not file_path:
            return

        dialog.destroy()

        # 显示进度对话框
        progress = tk.Toplevel(self)
        progress.title("导出进度")
        progress.geometry("300x100")
        ttk.Label(progress, text="正在导出书籍，请稍候...").pack(pady=20)
        progress.update()

        try:
            success, message = self.db.export_selected_books_to_excel(
                file_path,
                list(self.selected_books) if self.selected_books else None
            )
            progress.destroy()
            if success:
                messagebox.showinfo("成功", message)
            else:
                messagebox.showerror("错误", message)
        except Exception as e:
            progress.destroy()
            messagebox.showerror("错误", f"导出失败: {str(e)}")




